home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / misc / sci / RARS_Amiga_3.lha / RARS / AmigaInterface.c next >
Encoding:
C/C++ Source or Header  |  1995-05-27  |  35.5 KB  |  1,352 lines

  1. /*
  2.  * $RCSfile: AmigaInterface.c $
  3.  *
  4.  * $Author: marcel $
  5.  *
  6.  * $Revision: 1.1 $
  7.  *
  8.  * $Date: 1995/05/27 15:54:23 $
  9.  *
  10.  * $Locker: marcel $
  11.  *
  12.  * $State: Exp $
  13.  */
  14.  
  15. /* standard headers */
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19.  
  20. #include <exec/types.h>
  21. #include <exec/memory.h>
  22. #include <exec/lists.h>
  23. #include <exec/nodes.h>
  24. #include <graphics/text.h>
  25. #include <graphics/displayinfo.h>
  26. #include <graphics/gfxmacros.h>
  27. #include <intuition/intuition.h>
  28. #include <libraries/gadtools.h>
  29. #include <dos/exall.h>
  30. #include <dos/dostags.h>
  31. #include <dos/dos.h>
  32.  
  33. #include <clib/macros.h>
  34.  
  35. #include <proto/diskfont.h>
  36. #include <proto/exec.h>
  37. #include <proto/intuition.h>
  38. #include <proto/gadtools.h>
  39. #include <proto/graphics.h>
  40. #include <proto/dos.h>
  41. #include <proto/asl.h>
  42.  
  43. /* EAGUI headers */
  44. #include "EAGUI.h"
  45. #include "EAGUI_pragmas.h"
  46.  
  47. /* custom object */
  48. #include "TextField.c"
  49.  
  50. /* RARS interface */
  51. typedef struct con_vec { double alpha, vc; };
  52. typedef struct colors { int nose, tail; };
  53. typedef struct car_ID { struct con_vec *rob_ptr; struct colors paint_job; char *rob_name; };
  54. extern struct car_ID        drivers[];
  55. extern char                trackfile[];
  56. extern int                car_count;
  57. extern int                lap_count;
  58. extern int                race_count;
  59. extern int                real_speed;
  60. extern int                no_display;
  61. extern int                keep_order;
  62. extern int                randomotion;
  63. extern int                practice;
  64. extern int                surface;
  65. extern int                rndmiz;
  66. extern int                no_waiting;
  67. extern int                randomotion;
  68. extern int                practice;
  69.  
  70. /* defines */
  71. #define GADID_DRVAVAIL        1
  72. #define GADID_DRVSEL        2
  73. #define GADID_DRVADD        3
  74. #define GADID_DRVREMOVE        4
  75. #define GADID_DRVUP            5
  76. #define GADID_DRVDOWN        6
  77. #define GADID_TRACK            7
  78. #define GADID_PRACLAPS        8
  79. #define GADID_RACES            9
  80. #define GADID_LAPS            10
  81. #define GADID_SURFACE        11
  82. #define GADID_KEEPORDER        12
  83. #define GADID_NOREALTIME        13
  84. #define GADID_NODISPLAY        14
  85. #define GADID_NORANDOMSEED    15
  86. #define GADID_NORANDOM        16
  87. #define GADID_NOKEYBOARD        17
  88. #define GADID_SCREENMODE        18
  89. #define GADID_SCREENMODETEXT    19
  90. #define GADID_SAVE            20
  91. #define GADID_USE            21
  92. #define GADID_CANCEL        22
  93. #define GADID_COUNT            23
  94.  
  95. #define MAXCARS            16
  96. #define ENVBUFSIZE            1024
  97.  
  98. /* special defines that refer to tagitems inside taglists */
  99. #define tracknr            (tracktags[0].ti_Data)
  100. #define drvavailnr            (drvavailtags[0].ti_Data)
  101. #define drvselnr            (drvseltags[0].ti_Data)
  102.  
  103. /* globals */
  104. struct ScreenModeRequester *        smreq_ptr = NULL;
  105. struct NameInfo                nameinfo;
  106. ULONG                        scrdepth = 4;
  107. ULONG                        scrwidth = 640;
  108. ULONG                        scrheight = 480;
  109. ULONG                        scrid = HIRESLACE_KEY;
  110. ULONG                        scroscantype = OSCAN_TEXT;
  111. ULONG                        scrautoscroll = TRUE;
  112. STATIC ULONG                    wleft, wtop, wwidth, wheight;
  113. STATIC ULONG                    praclaps, races, laps, surfacetype;
  114. STATIC ULONG                    keeporder, nodisplay, norealtime, norandomseed, norandom, nokeyboard;
  115. STATIC struct List                tracklist;
  116. STATIC struct List                drvavaillist;
  117. STATIC struct List                drvsellist;
  118. STATIC struct ea_Object *        winobj_ptr        = NULL;
  119. STATIC struct Window *            win_ptr            = NULL;
  120. STATIC struct Screen *            scr_ptr            = NULL;
  121. STATIC struct Gadget *            gadlist_ptr        = NULL;
  122. STATIC struct Gadget *            gadget_ptr_ptr[GADID_COUNT];        /* array of gadget pointers */
  123. STATIC APTR                     visualinfo_ptr        = NULL;
  124. STATIC struct DrawInfo *            drawinfo_ptr        = NULL;
  125. STATIC struct TextFont *            tf_ptr            = NULL;
  126. struct Library *                EAGUIBase            = NULL;
  127. STATIC struct TextAttr             textattr             = {NULL, 0, FS_NORMAL, FPF_DISKFONT};
  128. STATIC struct Hook                relhook;
  129. STATIC struct Hook                tfminsizehook;
  130. STATIC struct Hook                tfrenderhook;
  131. STATIC struct IntuiMessage        imsg;
  132. STATIC struct ci_TextField        textfield1;
  133. STATIC BOOL                    cancelrars        = FALSE;        /* user clicked cancel/close */
  134. STATIC BOOL                    saveenv            = FALSE;        /* use or save */
  135. STATIC UBYTE                    rcs_id_string[]    = "$Id: AmigaInterface.c 1.1 1995/05/27 15:54:23 marcel Exp marcel $";
  136. STATIC STRPTR                    labels[]            = {
  137.                                             "Dirt",
  138.                                             "Paved",
  139.                                             NULL};
  140. STATIC struct TagItem            cytaglist1[]        = {
  141.                                             {GTCY_Labels,            (LONG)labels},
  142.                                             {GTCY_Active,            0},
  143.                                             {TAG_DONE}};
  144. STATIC struct TagItem            texttaglist1[]        = {
  145.                                             {GTTX_Border,            TRUE},
  146.                                             {GTTX_Text,            (ULONG)"default"},
  147.                                             {TAG_DONE}};
  148. STATIC struct TagItem            cbtaglist1[]        = {
  149.                                             {GTCB_Scaled,            TRUE},
  150.                                             {TAG_DONE}};
  151. STATIC struct TagItem            drvavailtags[]        = {
  152.                                             {GTLV_MakeVisible,        0},
  153.                                             {GTLV_Labels,            (ULONG)&drvavaillist},
  154.                                             {GTLV_ShowSelected,        NULL},
  155.                                             {TAG_DONE}};
  156. STATIC struct TagItem            drvseltags[]        = {
  157.                                             {GTLV_MakeVisible,        0},
  158.                                             {GTLV_Labels,            (ULONG)&drvsellist},
  159.                                             {GTLV_ShowSelected,        NULL},
  160.                                             {TAG_DONE}};
  161. STATIC struct TagItem            tracktags[]        = {
  162.                                             {GTLV_MakeVisible,        0},
  163.                                             {GTLV_Labels,            (ULONG)&tracklist},
  164.                                             {GTLV_ShowSelected,        NULL},
  165.                                             {TAG_DONE}};
  166. STATIC struct ea_Object *        gr1_ptr, *gr2_ptr, *gr3_ptr, *ob1_ptr, *ob2_ptr,
  167.                             *ob3_ptr, *ob4_ptr, *ob5_ptr, *ob6_ptr, *ob7_ptr,
  168.                             *ob8_ptr, *ob9_ptr, *ob10_ptr;
  169. STATIC UBYTE                    envbuf_ptr[ENVBUFSIZE];
  170. STATIC struct NewMenu                newmenu_ptr[] = {
  171.     {NM_TITLE,    "Project",            NULL,    0,    0,    NULL},
  172.     {NM_ITEM,        "About...",            "?",        0,    0,    NULL},
  173.     {NM_ITEM,        "Quit",                "Q",        0,    0,    NULL},
  174.     {NM_END,        NULL,                NULL,    0,    0,    NULL},
  175. };
  176. STATIC struct Menu *                menu_ptr;
  177.  
  178. /* prototypes */
  179. STATIC ULONG __saveds __asm        HookEntry(register __a0 struct Hook *, register __a2 VOID *, register __a1 VOID *);
  180. STATIC VOID                    InitHook(struct Hook *, ULONG (*)(), VOID *);
  181. STATIC ULONG                    rel_sameleftborder(struct Hook *, struct List *, APTR);
  182. STATIC LONG                    init(VOID);
  183. STATIC VOID                    cleanup(STRPTR);
  184. STATIC VOID                    resizewindow(VOID);
  185. STATIC ULONG                    handlemsgs(VOID);
  186.  
  187. /* cleanup a general list */
  188. STATIC VOID cleanup_list(struct List *list_ptr)
  189. {
  190.     struct Node *node_ptr;
  191.     struct Node *next_ptr;
  192.  
  193.     if (IsListEmpty(list_ptr))
  194.     {
  195.         return;
  196.     }
  197.  
  198.     node_ptr = list_ptr->lh_Head;
  199.     while (next_ptr = node_ptr->ln_Succ)
  200.     {
  201.         FreeVec(node_ptr->ln_Name);
  202.         FreeVec(node_ptr);
  203.         node_ptr = next_ptr;
  204.     }
  205. }
  206.  
  207. STATIC ULONG finddriver(STRPTR name_ptr)
  208. {
  209.     ULONG i;
  210.  
  211.     for (i = 0; i < MAXCARS; i++)
  212.     {
  213.         if (strcmp(name_ptr, drivers[i].rob_name) == 0)
  214.         {
  215.             return(i);
  216.         }
  217.     }
  218.     return(~0UL);
  219. }
  220.  
  221. STATIC STRPTR findname(struct List *list_ptr, ULONG number)
  222. {
  223.     struct Node *node_ptr;
  224.     ULONG nr;
  225.  
  226.     if (IsListEmpty(list_ptr))
  227.     {
  228.         return(NULL);
  229.     }
  230.  
  231.     node_ptr = list_ptr->lh_Head;
  232.     nr = 0;
  233.     while (node_ptr->ln_Succ)
  234.     {
  235.         if (nr == number)
  236.         {
  237.             return(node_ptr->ln_Name);
  238.         }
  239.         nr++;
  240.         node_ptr = node_ptr->ln_Succ;
  241.     }
  242.     return(NULL);
  243. }
  244.  
  245. STATIC ULONG findnr(struct List *list_ptr, STRPTR name_ptr)
  246. {
  247.     struct Node *node_ptr;
  248.     ULONG nr;
  249.  
  250.     if (IsListEmpty(list_ptr))
  251.     {
  252.         return(~(0UL));
  253.     }
  254.  
  255.     node_ptr = list_ptr->lh_Head;
  256.     nr = 0;
  257.     while (node_ptr->ln_Succ)
  258.     {
  259.         if (strcmp(node_ptr->ln_Name, name_ptr) == 0)
  260.         {
  261.             return(nr);
  262.         }
  263.         nr++;
  264.         node_ptr = node_ptr->ln_Succ;
  265.     }
  266.     return(~(0UL));
  267. }
  268.  
  269. STATIC VOID addsorted(struct List *list_ptr, struct Node *newnode_ptr)
  270. {
  271.     struct Node *node_ptr;
  272.  
  273.     if (!(IsListEmpty(list_ptr)))
  274.     {
  275.         node_ptr = list_ptr->lh_TailPred;
  276.         while (node_ptr->ln_Pred)
  277.         {
  278.             if (stricmp(node_ptr->ln_Name, newnode_ptr->ln_Name) < 0)
  279.             {
  280.                 Insert(list_ptr, newnode_ptr, node_ptr);
  281.                 return;
  282.             }
  283.             node_ptr = node_ptr->ln_Pred;
  284.         }
  285.     }
  286.     AddHead(list_ptr, newnode_ptr);
  287.     return;
  288. }
  289.  
  290. /* build driver lists */
  291. STATIC VOID buildlist_drivers(VOID)
  292. {
  293.     ULONG i;
  294.     struct Node *node_ptr;
  295.     STRPTR name_ptr;
  296.  
  297.     for (i = 0; i < MAXCARS; i++)
  298.     {
  299.         if (node_ptr = AllocVec(sizeof(struct Node), MEMF_PUBLIC | MEMF_CLEAR))
  300.         {
  301.             if (name_ptr = AllocVec(strlen(drivers[i].rob_name) + 1, MEMF_PUBLIC))
  302.             {
  303.                 strcpy(name_ptr, drivers[i].rob_name);
  304.                 node_ptr->ln_Name = name_ptr;
  305.                 if (i < car_count)
  306.                 {
  307.                     AddTail(&drvsellist, node_ptr);
  308.                 }
  309.                 else
  310.                 {
  311.                     addsorted(&drvavaillist, node_ptr);
  312.                 }
  313.             }
  314.             else
  315.             {
  316.                 FreeVec(node_ptr);
  317.             }
  318.         }
  319.     }
  320. }
  321.  
  322. /* scan directory for track files, and build the track list */
  323. STATIC VOID scandir_tracks(VOID)
  324. {
  325.     struct ExAllControl *    eac;
  326.     BPTR                    lock;
  327.     struct ExAllData         EAData[12]; /* 12 is arbitrarily chosen bufferlength */
  328.     int                    status = 0;
  329.     char *                 pattern_ptr;
  330.     BOOL                    more;
  331.     struct ExAllData *         ead;
  332.     struct Node *            node_ptr;
  333.     int                     namelength;
  334.  
  335.     if (!(pattern_ptr = AllocVec(2 * strlen("#?.trk") + 2, MEMF_PUBLIC)))
  336.     {
  337.         /* could not allocate parse buffer */
  338.         return;
  339.     }
  340.  
  341.     /* get lock on current directory */
  342.     lock = Lock("", ACCESS_READ);
  343.  
  344.     if (lock == 0)
  345.     {
  346.         /* could not lock operator directory */
  347.         FreeVec(pattern_ptr);
  348.         return;
  349.     }
  350.  
  351.     if (eac = AllocDosObject(DOS_EXALLCONTROL, NULL))
  352.     {
  353.         /* Init ExAll control structure */
  354.         eac->eac_LastKey = 0;
  355.         ParsePatternNoCase("#?.trk", pattern_ptr , 2 * strlen("#?.trk") + 2);
  356.         eac->eac_MatchString = (UBYTE *)pattern_ptr;
  357.  
  358.         /* Walk through directory */
  359.         do
  360.         {
  361.             more = ExAll(lock, EAData, sizeof(EAData), ED_NAME, eac);
  362.             if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) 
  363.             {
  364.                 /* ABNORMAL FAILURE */
  365.                 status = 20;
  366.             }
  367.             else if (eac->eac_Entries == 0) 
  368.             {
  369.                 /* NO ENTRIES */
  370.             }
  371.             else
  372.             {
  373.                 /* set pointer to first ExAllData structure in buffer */
  374.                 ead = (struct ExAllData *) EAData;
  375.                 do
  376.                 {
  377.                     /* allocate memory for track node and name */
  378.                     if (node_ptr = AllocVec(sizeof(struct Node), MEMF_CLEAR | MEMF_PUBLIC))
  379.                     {
  380.                         /* copy name to node, remove filename extension */
  381.                         namelength = strlen(ead->ed_Name) - 4;
  382.                         if (node_ptr->ln_Name = AllocVec(namelength + 1, MEMF_PUBLIC))
  383.                         {
  384.                             strncpy(node_ptr->ln_Name, ead->ed_Name, namelength);
  385.                             node_ptr->ln_Name[namelength] = '\0';
  386.  
  387.                             /* add to list */
  388.                             addsorted(&tracklist, node_ptr);
  389.                         }
  390.                         else
  391.                         {
  392.                             /* could not allocate string */
  393.                             FreeVec(node_ptr);
  394.                         }
  395.                     }
  396.                     /* to next element in buffer */
  397.                     ead = ead->ed_Next;
  398.                 } while (ead); 
  399.             }
  400.         } while (more); /* load next part of directory into the buffer */
  401.         FreeVec(pattern_ptr);
  402.         FreeDosObject(DOS_EXALLCONTROL, eac);
  403.     }
  404.     else
  405.     {
  406.         /* could not allocate dosobject */
  407.         status = 20;
  408.     }
  409.     /* Release directory */
  410.     UnLock(lock);
  411.     return;
  412. }
  413.  
  414. /* functions for hook handling */
  415. STATIC ULONG __saveds __asm HookEntry
  416. (
  417.     register __a0 struct Hook *    hook_ptr,
  418.     register __a2 VOID *        object_ptr,
  419.     register __a1 VOID *        message_ptr
  420. )
  421. {
  422.     return((*hook_ptr->h_SubEntry)(hook_ptr, object_ptr, message_ptr));
  423. }
  424.  
  425. STATIC VOID InitHook(struct Hook *h_ptr, ULONG (*func_ptr)(), VOID *data_ptr)
  426. {
  427.     if (h_ptr)
  428.     {
  429.         h_ptr->h_Entry = (ULONG (*)())HookEntry;
  430.         h_ptr->h_SubEntry = func_ptr;
  431.         h_ptr->h_Data = data_ptr;
  432.     }
  433. }
  434.  
  435. /* same leftborder relation */
  436. STATIC ULONG rel_sameleftborder(struct Hook *hook_ptr, struct List *list_ptr, APTR msg_ptr)
  437. {
  438.      struct ea_RelationObject *ro_ptr;
  439.      ULONG mlb;
  440.      ULONG lb;
  441.      mlb = 0;
  442.  
  443.      /* examine the list of objects that are affected by the relation */
  444.      ro_ptr = (struct ea_RelationObject *)list_ptr->lh_Head;
  445.      while (ro_ptr->node.ln_Succ)
  446.      {
  447.           lb = ea_GetAttr(ro_ptr->object_ptr, EA_BorderLeft);
  448.  
  449.           /* find the maximum values of the minimum sizes */
  450.           mlb = MAX(lb, mlb);
  451.  
  452.           ro_ptr = (struct ea_RelationObject *)ro_ptr->node.ln_Succ;
  453.      }
  454.  
  455.      /* set all objects to the newly found minimum sizes */
  456.      ro_ptr = (struct ea_RelationObject *)list_ptr->lh_Head;
  457.      while (ro_ptr->node.ln_Succ)
  458.      {
  459.           ea_SetAttr(ro_ptr->object_ptr, EA_BorderLeft, mlb);
  460.  
  461.           ro_ptr = (struct ea_RelationObject *)ro_ptr->node.ln_Succ;
  462.      }
  463.      return(0);
  464. }
  465.  
  466. /* initialize everything */
  467. STATIC LONG init(VOID)
  468. {
  469.     LONG w, h, bl, br, bt, bb;
  470.  
  471.     /* open the EAGUI library */
  472.     if (!(EAGUIBase = OpenLibrary(EAGUILIBRARYNAME, EAGUILIBRARYVERSION)))
  473.     {
  474.         cleanup("Couldn't open EAGUI.library.\n");
  475.     }
  476.  
  477.     /* lock the screen */
  478.     if (!(scr_ptr = LockPubScreen(NULL)))
  479.     {
  480.         cleanup("Couldn't lock default public screen.\n");
  481.     }
  482.  
  483.     /* get the screen font */
  484.     textattr.ta_Name = (STRPTR)(scr_ptr->RastPort.Font->tf_Message.mn_Node.ln_Name);
  485.     textattr.ta_YSize = scr_ptr->RastPort.Font->tf_YSize;
  486.  
  487.     /* open the font */
  488.     if (!(tf_ptr = OpenDiskFont(&textattr)))
  489.     {
  490.         cleanup("Couldn't open font.\n");
  491.     }
  492.  
  493.     /* initialize the relation */
  494.     InitHook(&relhook, rel_sameleftborder, NULL);
  495.  
  496.     /* initialize textfield hooks */
  497.     InitHook(&tfminsizehook, meth_MinSize_TextField, NULL);
  498.     InitHook(&tfrenderhook, meth_Render_TextField, NULL);
  499.  
  500.     /* set up some defaults for all objects */
  501.     ea_SetAttr(NULL, EA_DefGTTextAttr, (ULONG)&textattr);
  502.  
  503.     /* now we can build the object tree */
  504.     if (!( winobj_ptr = VGroup
  505.         EA_BorderLeft,        4,
  506.         EA_BorderRight,    4,
  507.         EA_BorderTop,        4,
  508.         EA_BorderBottom,    4,
  509.         EA_Child,            ea_NewObject(EA_TYPE_CUSTOMIMAGE,
  510.             EA_MinSizeMethod,    &tfminsizehook,
  511.             EA_RenderMethod,    &tfrenderhook,
  512.             EA_UserData,        &textfield1,
  513.             TAG_DONE),
  514.         EA_Child,            HGroup
  515.             EA_Weight,        1,
  516.             EA_Child,            GTListView("Available")
  517.                 EA_ID,            GADID_DRVAVAIL,
  518.                 EA_InstanceAddress,    &gadget_ptr_ptr[GADID_DRVAVAIL],
  519.                 EA_Weight,        3,
  520.                 EA_GTTagList,        drvavailtags,
  521.                 End,
  522.             EA_Child,            VGroup
  523.                 EA_BorderLeft,        4,
  524.                 EA_BorderRight,    4,
  525.                 EA_Weight,        1,
  526.                 EA_Child,            EmptyBox(1)
  527.                     End,
  528.                 EA_Child,            GTButton("Add")
  529.                     EA_ID,            GADID_DRVADD,
  530.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_DRVADD],
  531.                     EA_BorderBottom,    2,
  532.                     End,
  533.                 EA_Child,            GTButton("Remove")
  534.                     EA_ID,            GADID_DRVREMOVE,
  535.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_DRVREMOVE],
  536.                     EA_BorderTop,        2,
  537.                     EA_BorderBottom,    2,
  538.                     End,
  539.                 EA_Child,            GTButton("Up")
  540.                     EA_ID,            GADID_DRVUP,
  541.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_DRVUP],
  542.                     EA_BorderTop,        2,
  543.                     EA_BorderBottom,    2,
  544.                     End,
  545.                 EA_Child,            GTButton("Down")
  546.                     EA_ID,            GADID_DRVDOWN,
  547.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_DRVDOWN],
  548.                     EA_BorderTop,        2,
  549.                     End,
  550.                 EA_Child,            EmptyBox(1)
  551.                     End,
  552.                 End,
  553.             EA_Child,            GTListView("Selected")
  554.                 EA_ID,            GADID_DRVSEL,
  555.                 EA_InstanceAddress,    &gadget_ptr_ptr[GADID_DRVSEL],
  556.                 EA_Weight,        3,
  557.                 EA_GTTagList,        drvseltags,
  558.                 End,
  559.             End,
  560.         EA_Child,            HGroup
  561.             EA_Weight,        1,
  562.             EA_Child,            GTListView("Track")
  563.                 EA_ID,            GADID_TRACK,
  564.                 EA_InstanceAddress,    &gadget_ptr_ptr[GADID_TRACK],
  565.                 EA_Weight,        1,
  566.                 EA_GTTagList,    tracktags,
  567.                 End,
  568.             EA_Child,            gr1_ptr = VGroup
  569.                 EA_BorderLeft,        4,
  570.                 EA_Weight,        1,
  571.                 EA_Child,            EmptyBox(1)
  572.                     End,
  573.                 EA_Child,            ob1_ptr = GTInteger("Practice laps")
  574.                     EA_ID,            GADID_PRACLAPS,
  575.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_PRACLAPS],
  576.                     EA_BorderBottom,    2,
  577.                     End,
  578.                 EA_Child,            ob2_ptr = GTInteger("Races")
  579.                     EA_ID,            GADID_RACES,
  580.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_RACES],
  581.                     EA_BorderBottom,    2,
  582.                     EA_BorderTop,        2,
  583.                     End,
  584.                 EA_Child,            ob3_ptr = GTInteger("Laps")
  585.                     EA_ID,            GADID_LAPS,
  586.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_LAPS],
  587.                     EA_BorderBottom,    2,
  588.                     EA_BorderTop,        2,
  589.                     End,
  590.                 EA_Child,            ob4_ptr = GTCycle
  591.                     EA_ID,            GADID_SURFACE,
  592.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_SURFACE],
  593.                     EA_BorderTop,        2,
  594.                     EA_GTText,        "Surface",
  595.                     EA_GTTagList,        cytaglist1,
  596.                     End,
  597.                 EA_Child,            EmptyBox(1)
  598.                     End,
  599.                 End,
  600.             End,
  601.         EA_Child,            HGroup
  602.             EA_BorderTop,        4,
  603.             EA_BorderBottom,    4,
  604.             EA_Child,            EmptyBox(1)
  605.                 End,
  606.             EA_Child,            gr2_ptr = VGroup
  607.                 EA_Child,            ob5_ptr = GTCheckBox("Keep order")
  608.                     EA_ID,            GADID_KEEPORDER,
  609.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_KEEPORDER],
  610.                     EA_GTTagList,        cbtaglist1,
  611.                     EA_BorderBottom,    2,
  612.                     End,
  613.                 EA_Child,            ob6_ptr = GTCheckBox("No realtime")
  614.                     EA_ID,            GADID_NOREALTIME,
  615.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_NOREALTIME],
  616.                     EA_GTTagList,        cbtaglist1,
  617.                     EA_BorderBottom,    2,
  618.                     EA_BorderTop,        2,
  619.                     End,
  620.                 EA_Child,            ob7_ptr = GTCheckBox("No display")
  621.                     EA_ID,            GADID_NODISPLAY,
  622.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_NODISPLAY],
  623.                     EA_GTTagList,        cbtaglist1,
  624.                     EA_BorderTop,        2,
  625.                     End,
  626.                 End,
  627.             EA_Child,            EmptyBox(1)
  628.                 End,
  629.             EA_Child,            gr3_ptr = VGroup
  630.                 EA_Child,            ob8_ptr = GTCheckBox("No random seed")
  631.                     EA_ID,            GADID_NORANDOMSEED,
  632.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_NORANDOMSEED],
  633.                     EA_GTTagList,        cbtaglist1,
  634.                     EA_BorderBottom,    2,
  635.                     End,
  636.                 EA_Child,            ob9_ptr = GTCheckBox("No random")
  637.                     EA_ID,            GADID_NORANDOM,
  638.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_NORANDOM],
  639.                     EA_GTTagList,        cbtaglist1,
  640.                     EA_BorderBottom,    2,
  641.                     EA_BorderTop,        2,
  642.                     End,
  643.                 EA_Child,            ob10_ptr = GTCheckBox("No keyboard")
  644.                     EA_ID,            GADID_NOKEYBOARD,
  645.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_NOKEYBOARD],
  646.                     EA_GTTagList,        cbtaglist1,
  647.                     EA_BorderTop,        2,
  648.                     End,
  649.                 End,
  650.             End,
  651.         EA_Child,            HGroup
  652.             EA_Child,            GTButton("Screenmode...")
  653.                     EA_ID,            GADID_SCREENMODE,
  654.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_SCREENMODE],
  655.                 EA_Weight,        1,
  656.                 End,
  657.             EA_Child,            GTText(NULL)
  658.                     EA_ID,            GADID_SCREENMODETEXT,
  659.                     EA_InstanceAddress,    &gadget_ptr_ptr[GADID_SCREENMODETEXT],
  660.                 EA_Weight,        3,
  661.                 EA_GTTagList,        texttaglist1,
  662.                 End,
  663.             End,
  664.         EA_Child,            HGroup
  665.             EA_BorderTop,        4,
  666.             EA_Child,            GTButton("Save")
  667.                 EA_ID,            GADID_SAVE,
  668.                 EA_InstanceAddress,    &gadget_ptr_ptr[GADID_SAVE],
  669.                 EA_Weight,        1,
  670.                 End,
  671.             EA_Child,            EmptyBox(2)
  672.                 End,
  673.             EA_Child,            GTButton("Use")
  674.                 EA_ID,            GADID_USE,
  675.                 EA_InstanceAddress,    &gadget_ptr_ptr[GADID_USE],
  676.                 EA_Weight,        1,
  677.                 End,
  678.             EA_Child,            EmptyBox(2)
  679.                 End,
  680.             EA_Child,            GTButton("Cancel")
  681.                 EA_ID,            GADID_CANCEL,
  682.                 EA_InstanceAddress,    &gadget_ptr_ptr[GADID_CANCEL],
  683.                 EA_Weight,        1,
  684.                 End,
  685.             End,
  686.         End ) )
  687.     {
  688.         cleanup("Couldn't init the objects.\n");
  689.     }
  690.  
  691.     /* layout relations */
  692.      ea_NewRelation(gr1_ptr, &relhook,
  693.           EA_Object,          ob1_ptr,
  694.           EA_Object,          ob2_ptr,
  695.           EA_Object,          ob3_ptr,
  696.           EA_Object,          ob4_ptr,
  697.           TAG_DONE);
  698.      ea_NewRelation(gr2_ptr, &relhook,
  699.           EA_Object,          ob5_ptr,
  700.           EA_Object,          ob6_ptr,
  701.           EA_Object,          ob7_ptr,
  702.           TAG_DONE);
  703.      ea_NewRelation(gr3_ptr, &relhook,
  704.           EA_Object,          ob8_ptr,
  705.           EA_Object,          ob9_ptr,
  706.           EA_Object,          ob10_ptr,
  707.           TAG_DONE);
  708.  
  709.     /* get VisualInfo and DrawInfo */
  710.     if (!(visualinfo_ptr = GetVisualInfo(scr_ptr, TAG_DONE)))
  711.     {
  712.         cleanup("Couldn't get the visual info.\n");
  713.     }
  714.     if (!(drawinfo_ptr = GetScreenDrawInfo(scr_ptr)))
  715.     {
  716.         cleanup("Couldn't get the draw info.\n");
  717.     }
  718.  
  719.     /* fill in the textfield structure */
  720.     textfield1.tf_string_ptr = "Drivers";                /* title */
  721.     textfield1.tf_textattr_ptr = &textattr;                /* font */
  722.     textfield1.tf_flags = CITF_ALIGNTOP;                /* alignment flags */
  723.     textfield1.tf_frontpen = 1;                        /* frontpen color index */
  724.  
  725.     /* create the menu */
  726.     if (!(menu_ptr = CreateMenusA(newmenu_ptr, NULL)))
  727.     {
  728.         cleanup("Couldn't create the menu.\n");
  729.     }
  730.     if (LayoutMenus(menu_ptr, visualinfo_ptr,
  731.         GTMN_NewLookMenus,        TRUE,
  732.         TAG_DONE) == FALSE)
  733.     {
  734.         cleanup("Couldn't layout the menu.\n");
  735.     }
  736.  
  737.      /* obtain the minimum dimensions of every object in the tree */
  738.      ea_GetMinSizes(winobj_ptr);
  739.  
  740.     /* get some attributes */
  741.     ea_GetAttrs(winobj_ptr,
  742.         EA_MinWidth,        &w,
  743.         EA_MinHeight,        &h,
  744.         EA_BorderLeft,        &bl,
  745.         EA_BorderRight,    &br,
  746.         EA_BorderTop,        &bt,
  747.         EA_BorderBottom,    &bb,
  748.         TAG_DONE);
  749.  
  750.     /* get the environment variable that contains the window dimensions */
  751.     if (GetVar("RARSWINDOW", (STRPTR)envbuf_ptr, (long)ENVBUFSIZE, (long)0) > 0)
  752.     {
  753.         sscanf(envbuf_ptr, "%d %d %d %d", &wleft, &wtop, &wwidth, &wheight);
  754.     }
  755.     else
  756.     {
  757.         /* use defaults for window dimensions */
  758.         wheight = (h + bt + bb) * 3 / 2;
  759.         wwidth = (w + bl + br) * 2;
  760.         wleft = 0;
  761.         wtop = 0;
  762.     }
  763.  
  764.      /* open the window */
  765.      if (!(win_ptr = OpenWindowTags(NULL,
  766.         WA_ScreenTitle,    "RARS Amiga - Copyright © 1995 Marcel Offermans",
  767.          WA_Title,            "RARS Amiga",
  768.         WA_Flags,            (WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM | WFLG_ACTIVATE | WFLG_NEWLOOKMENUS),
  769.         WA_IDCMP,            (IDCMP_CLOSEWINDOW | BUTTONIDCMP | INTEGERIDCMP | CYCLEIDCMP | LISTVIEWIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_NEWSIZE | IDCMP_MENUPICK),
  770.         WA_Left,            wleft,
  771.         WA_Top,            wtop,
  772.         WA_Width,            wwidth,
  773.         WA_Height,        wheight,
  774.         TAG_DONE)))
  775.     {
  776.         cleanup("Couldn't open the window.\n");
  777.     }
  778.  
  779.     /* set the window limits */
  780.     WindowLimits(
  781.         win_ptr,
  782.         w + win_ptr->BorderLeft + win_ptr->BorderRight + bl + br,
  783.         h + win_ptr->BorderTop + win_ptr->BorderBottom + bt + bb,
  784.         ~0,
  785.         ~0);
  786.  
  787.     /* add the menu to this window */
  788.     SetMenuStrip(win_ptr, menu_ptr);
  789.  
  790.     /* create the gadgets and add them to the window */
  791.     resizewindow();
  792.  
  793.     if (!(smreq_ptr = (struct ScreenModeRequester *)AllocAslRequest(ASL_ScreenModeRequest, NULL)))
  794.     {
  795.         cleanup("Couldn't allocate screenmode requester.");
  796.     }
  797.     return(0);
  798. }
  799.  
  800. /* clean up everything that was created */
  801. STATIC VOID cleanup(STRPTR str_ptr)
  802. {
  803.     int rc = 0;
  804.  
  805.     /* if a string is passed, we assume there was some kind of error */
  806.     if (str_ptr)
  807.     {
  808.         Printf("Error: %s", str_ptr);
  809.         rc = 20;
  810.     }
  811.  
  812.     if (smreq_ptr)
  813.     {
  814.         FreeAslRequest(smreq_ptr);
  815.         smreq_ptr = NULL;
  816.     }
  817.  
  818.     if (gadlist_ptr)
  819.     {
  820.         RemoveGList(win_ptr, gadlist_ptr, -1);
  821.         ea_FreeGadgetList(winobj_ptr, gadlist_ptr);
  822.         gadlist_ptr = NULL;
  823.     }
  824.  
  825.     if (win_ptr)
  826.     {
  827.         CloseWindow(win_ptr);
  828.         win_ptr = NULL;
  829.     }
  830.  
  831.     if (menu_ptr)
  832.     {
  833.         FreeMenus(menu_ptr);
  834.         menu_ptr = NULL;
  835.     }
  836.  
  837.     if (drawinfo_ptr)
  838.     {
  839.         FreeScreenDrawInfo(scr_ptr, drawinfo_ptr);
  840.         drawinfo_ptr = NULL;
  841.     }
  842.  
  843.     if (visualinfo_ptr)
  844.     {
  845.         FreeVisualInfo(visualinfo_ptr);
  846.         visualinfo_ptr = NULL;
  847.     }
  848.  
  849.     if (winobj_ptr)
  850.     {
  851.         ea_DisposeObject(winobj_ptr);
  852.         winobj_ptr = NULL;
  853.     }
  854.  
  855.     if (tf_ptr)
  856.     {
  857.         CloseFont(tf_ptr);
  858.         tf_ptr = NULL;
  859.     }
  860.  
  861.     if (scr_ptr)
  862.     {
  863.         UnlockPubScreen(NULL, scr_ptr);
  864.         scr_ptr = NULL;
  865.     }
  866.  
  867.     if (EAGUIBase)
  868.     {
  869.         CloseLibrary(EAGUIBase);
  870.         EAGUIBase = NULL;
  871.     }
  872.  
  873.     /* cleanup lists */
  874.     cleanup_list(&tracklist);
  875.     cleanup_list(&drvavaillist);
  876.     cleanup_list(&drvsellist);
  877.  
  878.     if (rc > 0)
  879.     {
  880.         exit(rc);
  881.     }
  882. }
  883.  
  884. /* getstate */
  885. STATIC VOID getstate(VOID)
  886. {
  887.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_TRACK], win_ptr, NULL, GTLV_Selected, &tracknr, TAG_DONE);
  888.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Selected, &drvavailnr, TAG_DONE);
  889.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Selected, &drvselnr, TAG_DONE);
  890.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_PRACLAPS], win_ptr, NULL, GTIN_Number, &praclaps, TAG_DONE);
  891.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_RACES], win_ptr, NULL, GTIN_Number, &races, TAG_DONE);
  892.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_LAPS], win_ptr, NULL, GTIN_Number, &laps, TAG_DONE);
  893.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_SURFACE], win_ptr, NULL, GTCY_Active, &surfacetype, TAG_DONE);
  894.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_KEEPORDER], win_ptr, NULL, GTCB_Checked, &keeporder, TAG_DONE);
  895.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_NOREALTIME], win_ptr, NULL, GTCB_Checked, &norealtime, TAG_DONE);
  896.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_NODISPLAY], win_ptr, NULL, GTCB_Checked, &nodisplay, TAG_DONE);
  897.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_NORANDOMSEED], win_ptr, NULL, GTCB_Checked, &norandomseed, TAG_DONE);
  898.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_NORANDOM], win_ptr, NULL, GTCB_Checked, &norandom, TAG_DONE);
  899.     GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_NOKEYBOARD], win_ptr, NULL, GTCB_Checked, &nokeyboard, TAG_DONE);
  900. }
  901.  
  902. /* setstate */
  903. STATIC VOID setstate(VOID)
  904. {
  905.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_TRACK], win_ptr, NULL, GTLV_Selected, tracknr, TAG_DONE);
  906.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Selected, drvavailnr, TAG_DONE);
  907.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Selected, drvselnr, TAG_DONE);
  908.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_PRACLAPS], win_ptr, NULL, GTIN_Number, praclaps, TAG_DONE);
  909.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_RACES], win_ptr, NULL, GTIN_Number, races, TAG_DONE);
  910.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_LAPS], win_ptr, NULL, GTIN_Number, laps, TAG_DONE);
  911.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_SURFACE], win_ptr, NULL, GTCY_Active, surfacetype, TAG_DONE);
  912.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_KEEPORDER], win_ptr, NULL, GTCB_Checked, keeporder, TAG_DONE);
  913.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_NOREALTIME], win_ptr, NULL, GTCB_Checked, norealtime, TAG_DONE);
  914.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_NODISPLAY], win_ptr, NULL, GTCB_Checked, nodisplay, TAG_DONE);
  915.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_NORANDOMSEED], win_ptr, NULL, GTCB_Checked, norandomseed, TAG_DONE);
  916.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_NORANDOM], win_ptr, NULL, GTCB_Checked, norandom, TAG_DONE);
  917.     GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_NOKEYBOARD], win_ptr, NULL, GTCB_Checked, nokeyboard, TAG_DONE);
  918.     if (GetDisplayInfoData(NULL, (UBYTE *)&nameinfo, sizeof(struct NameInfo), DTAG_NAME, scrid))
  919.     {
  920.         GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_SCREENMODETEXT], win_ptr, NULL, GTTX_Text, nameinfo.Name, TAG_DONE);
  921.     }
  922. }
  923.  
  924. /* (re)create the gadget list */
  925. STATIC VOID resizewindow(VOID)
  926. {
  927.     LONG bl, br, bt, bb;
  928.  
  929.     /* get gadget state */
  930.     getstate();
  931.  
  932.     /* if necessary, remove the gadget list from the window, and clean it up */
  933.     if (gadlist_ptr)
  934.     {
  935.         RemoveGList(win_ptr, gadlist_ptr, -1);
  936.         ea_FreeGadgetList(winobj_ptr, gadlist_ptr);
  937.         gadlist_ptr = NULL;
  938.     }
  939.  
  940.     ea_GetAttrs(winobj_ptr,
  941.         EA_BorderLeft,        &bl,
  942.         EA_BorderRight,    &br,
  943.         EA_BorderTop,        &bt,
  944.         EA_BorderBottom,    &bb,
  945.         TAG_DONE);
  946.  
  947.      ea_SetAttrs(winobj_ptr,
  948.         EA_Width,        win_ptr->Width -
  949.                     win_ptr->BorderLeft -
  950.                     win_ptr->BorderRight -
  951.                     bl -
  952.                     br,
  953.         EA_Height,    win_ptr->Height -
  954.                     win_ptr->BorderTop -
  955.                     win_ptr->BorderBottom -
  956.                     bt -
  957.                     bb,
  958.         EA_Left,        win_ptr->BorderLeft,
  959.         EA_Top,        win_ptr->BorderTop,
  960.         TAG_DONE);
  961.  
  962.     ea_LayoutObjects(winobj_ptr);
  963.  
  964.     if (ea_CreateGadgetList(winobj_ptr, &gadlist_ptr, visualinfo_ptr, drawinfo_ptr) != EA_ERROR_OK)
  965.     {     
  966.         cleanup("Couldn't create the gadget list.\n");
  967.     }     
  968.  
  969.     EraseRect(win_ptr->RPort,     
  970.         win_ptr->BorderLeft,
  971.         win_ptr->BorderTop,
  972.         win_ptr->Width - win_ptr->BorderRight - 1,
  973.         win_ptr->Height - win_ptr->BorderBottom - 1);
  974.  
  975.     RefreshWindowFrame(win_ptr);
  976.  
  977.     AddGList(win_ptr, gadlist_ptr, -1, -1, NULL);
  978.     RefreshGList(gadlist_ptr, win_ptr, NULL, -1);
  979.     GT_RefreshWindow(win_ptr, NULL);
  980.  
  981.     /* finally, we render the imagery, if there is any */
  982.     ea_RenderObjects(winobj_ptr, win_ptr->RPort);
  983.  
  984.     /* set gadget state */
  985.     setstate();
  986. }
  987.  
  988. VOID about_rars(VOID)
  989. {
  990.     struct EasyStruct es = {
  991.         sizeof(struct EasyStruct),
  992.         0,
  993.         "About RARS Amiga",
  994.         "Robot Auto Racing Simulation\n\n"
  995.         "Amiga version\n\n"
  996.         "Copyright © 1995 Marcel Offermans",
  997.         "Ok"};
  998.  
  999.     EasyRequest(NULL, &es, NULL, NULL);
  1000. }
  1001.  
  1002. /* a normal message handling loop */
  1003. STATIC ULONG handlemsgs(VOID)
  1004. {
  1005.     struct IntuiMessage    *    imsg_ptr;
  1006.     ULONG                rc = 0;
  1007.     struct Node *            node_ptr;
  1008.     struct Node *            node2_ptr;
  1009.     ULONG                nr;
  1010.     STRPTR                name_ptr;
  1011.     struct MenuItem *        menuitem_ptr;
  1012.  
  1013.     while (imsg_ptr = GT_GetIMsg(win_ptr->UserPort))
  1014.     {
  1015.         CopyMem((char *)imsg_ptr, (char *)&imsg, (long)sizeof(struct IntuiMessage));
  1016.  
  1017.         GT_ReplyIMsg(imsg_ptr);
  1018.  
  1019.         switch (imsg.Class)
  1020.         {
  1021.             case IDCMP_MENUPICK:
  1022.                 while (imsg.Code != MENUNULL)
  1023.                 {
  1024.                     menuitem_ptr = ItemAddress(menu_ptr, imsg.Code);
  1025.                     switch (MENUNUM(imsg.Code))
  1026.                     {
  1027.                         case 0:    /* Project */
  1028.                             switch(ITEMNUM(imsg.Code))
  1029.                             {
  1030.                                 case 0:    /* About... */
  1031.                                     about_rars();
  1032.                                     break;
  1033.                                 case 1:    /* Quit */
  1034.                                     rc = 10;
  1035.                                     cancelrars = TRUE;
  1036.                                     break;
  1037.                             }
  1038.                             break;
  1039.                     }
  1040.                     imsg.Code = menuitem_ptr->NextSelect;
  1041.                 }
  1042.                 break;
  1043.  
  1044.             case    IDCMP_REFRESHWINDOW:
  1045.                 GT_BeginRefresh(win_ptr);
  1046.                 GT_EndRefresh(win_ptr, TRUE);
  1047.                 break;
  1048.  
  1049.             case    IDCMP_CLOSEWINDOW:
  1050.                 rc = 10;
  1051.                 cancelrars = TRUE;
  1052.                 break;
  1053.  
  1054.             case IDCMP_GADGETUP:
  1055.             case IDCMP_GADGETDOWN:
  1056.                 switch (((struct Gadget *)imsg.IAddress)->GadgetID)
  1057.                 {
  1058.                     case GADID_SAVE:
  1059.                         saveenv = TRUE;
  1060.                         rc = 10;
  1061.                         break;
  1062.                     case GADID_USE:
  1063.                         saveenv = FALSE;
  1064.                         rc = 10;
  1065.                         break;
  1066.                     case GADID_CANCEL:
  1067.                         rc = 10;
  1068.                         cancelrars = TRUE;
  1069.                         break;
  1070.                     case GADID_DRVADD:
  1071.                         /* search for driver in available list */
  1072.                         GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Selected, &nr, TAG_DONE);
  1073.                         if (name_ptr = findname(&drvavaillist, nr))
  1074.                         {
  1075.                             node_ptr = FindName(&drvavaillist, name_ptr);
  1076.  
  1077.                             /* deactivate listviews */
  1078.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Labels, ~0, TAG_DONE);
  1079.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, ~0, TAG_DONE);
  1080.  
  1081.                             /* remove driver from list */
  1082.                             Remove(node_ptr);
  1083.  
  1084.                             /* add driver to list */
  1085.                             AddTail(&drvsellist, node_ptr);
  1086.  
  1087.                             /* activate listviews */
  1088.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Labels, &drvavaillist, TAG_DONE);
  1089.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, &drvsellist, TAG_DONE);
  1090.                         }
  1091.                         break;
  1092.  
  1093.                     case GADID_DRVREMOVE:
  1094.                         /* search for driver in selected list */
  1095.                         GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Selected, &nr, TAG_DONE);
  1096.                         if (name_ptr = findname(&drvsellist, nr))
  1097.                         {
  1098.                             node_ptr = FindName(&drvsellist, name_ptr);
  1099.  
  1100.                             /* deactivate listviews */
  1101.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Labels, ~0, TAG_DONE);
  1102.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, ~0, TAG_DONE);
  1103.  
  1104.                             /* remove driver from list */
  1105.                             Remove(node_ptr);
  1106.  
  1107.                             /* add driver to list */
  1108.                             addsorted(&drvavaillist, node_ptr);
  1109.  
  1110.                             /* activate listviews */
  1111.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVAVAIL], win_ptr, NULL, GTLV_Labels, &drvavaillist, TAG_DONE);
  1112.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, &drvsellist, TAG_DONE);
  1113.                         }
  1114.                         break;
  1115.  
  1116.                     case GADID_DRVUP:
  1117.                         /* search for driver in selected list */
  1118.                         GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Selected, &nr, TAG_DONE);
  1119.                         if (name_ptr = findname(&drvsellist, nr))
  1120.                         {
  1121.                             node_ptr = FindName(&drvsellist, name_ptr);
  1122.  
  1123.                             /* deactivate listview */
  1124.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, ~0, TAG_DONE);
  1125.  
  1126.                             /* get the node before the current one */
  1127.                             node2_ptr = node_ptr->ln_Pred->ln_Pred;
  1128.  
  1129.                             /* if we're not at the start of the list... */
  1130.                             if (node2_ptr)
  1131.                             {
  1132.                                 /* remove driver from list */
  1133.                                 Remove(node_ptr);
  1134.  
  1135.                                 /* add driver to list */
  1136.                                 Insert(&drvavaillist, node_ptr, node2_ptr);
  1137.                                 nr--;
  1138.                             }
  1139.  
  1140.                             /* activate listview */
  1141.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, &drvsellist, GTLV_Selected, nr, TAG_DONE);
  1142.                         }
  1143.                         break;
  1144.                     case GADID_DRVDOWN:
  1145.                         /* search for driver in selected list */
  1146.                         GT_GetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Selected, &nr, TAG_DONE);
  1147.                         if (name_ptr = findname(&drvsellist, nr))
  1148.                         {
  1149.                             node_ptr = FindName(&drvsellist, name_ptr);
  1150.  
  1151.                             /* deactivate listview */
  1152.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, ~0, TAG_DONE);
  1153.  
  1154.                             /* get the node before the current one */
  1155.                             node2_ptr = node_ptr->ln_Succ;
  1156.  
  1157.                             /* remove driver from list */
  1158.                             Remove(node_ptr);
  1159.  
  1160.                             /* add driver to list */
  1161.                             if (node2_ptr)
  1162.                             {
  1163.                                 Insert(&drvavaillist, node_ptr, node2_ptr);
  1164.                                 nr++;
  1165.                             }
  1166.                             else
  1167.                             {
  1168.                                 AddTail(&drvavaillist, node_ptr);
  1169.                             }
  1170.  
  1171.                             /* activate listview */
  1172.                             GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_DRVSEL], win_ptr, NULL, GTLV_Labels, &drvsellist, GTLV_Selected, nr, TAG_DONE);
  1173.                         }
  1174.                         break;
  1175.                     case GADID_SCREENMODE:
  1176.                         if (AslRequestTags(smreq_ptr,
  1177.                             ASLSM_PrivateIDCMP,            TRUE,
  1178.                             ASLSM_TitleText,            "Select a screenmode for RARS screen...",
  1179.                             ASLSM_PositiveText,            "Ok",
  1180.                             ASLSM_NegativeText,            "Cancel",
  1181.                             ASLSM_InitialDisplayDepth,    scrdepth,
  1182.                             ASLSM_InitialDisplayWidth,    scrwidth,
  1183.                             ASLSM_InitialDisplayHeight,    scrheight,
  1184.                             ASLSM_InitialDisplayID,        scrid,
  1185.                             ASLSM_InitialOverscanType,    scroscantype,
  1186.                             ASLSM_InitialHeight,        400,
  1187.                             ASLSM_DoWidth,                TRUE,
  1188.                             ASLSM_DoHeight,            TRUE,
  1189.                             ASLSM_DoDepth,                TRUE,
  1190.                             ASLSM_DoOverscanType,        TRUE,
  1191.                             ASLSM_DoAutoScroll,            TRUE,
  1192.                             ASLSM_SleepWindow,            TRUE,
  1193.                             ASLSM_Window,                win_ptr,
  1194.                             TAG_DONE))
  1195.                         {
  1196.                             scrdepth = smreq_ptr->sm_DisplayDepth;
  1197.                             scrwidth = smreq_ptr->sm_DisplayWidth;
  1198.                             scrheight = smreq_ptr->sm_DisplayHeight;
  1199.                             scrid = smreq_ptr->sm_DisplayID;
  1200.                             scroscantype = smreq_ptr->sm_OverscanType;
  1201.                             scrautoscroll = smreq_ptr->sm_AutoScroll;
  1202.  
  1203.                             /* and update the text gadget to show the new mode */
  1204.                             if (GetDisplayInfoData(NULL, (UBYTE *)&nameinfo, sizeof(struct NameInfo), DTAG_NAME, scrid))
  1205.                             {
  1206.                                 GT_SetGadgetAttrs(gadget_ptr_ptr[GADID_SCREENMODETEXT], win_ptr, NULL, GTTX_Text, nameinfo.Name, TAG_DONE);
  1207.                             }
  1208.                         }
  1209.                         break;
  1210.                 }
  1211.                 break;
  1212.  
  1213.             case    IDCMP_NEWSIZE:
  1214.                 resizewindow();
  1215.                 break;
  1216.         }
  1217.     }
  1218.     return(rc);
  1219. }
  1220.  
  1221. VOID show_gui(VOID)
  1222. {
  1223.     ULONG idcmpmask, signals;
  1224.     BOOL done = FALSE;
  1225.     struct Node *node_ptr;
  1226.     ULONG i;
  1227.     struct car_ID temp_drv;
  1228.  
  1229.     /* initialize the lists */
  1230.     NewList(&tracklist);
  1231.     NewList(&drvavaillist);
  1232.     NewList(&drvsellist);
  1233.  
  1234.     /* get a list of tracks */
  1235.     scandir_tracks();
  1236.  
  1237.     /* build the driver lists */
  1238.     buildlist_drivers();
  1239.  
  1240.     /* copy globals from RARS to the local variables */
  1241.     laps = lap_count;
  1242.     races = race_count;
  1243.     praclaps = practice;
  1244.     surfacetype = surface;
  1245.     keeporder = (keep_order == 1);
  1246.     nodisplay = (no_display == 1);
  1247.     norealtime = (real_speed == 0);
  1248.     norandomseed = (rndmiz == 0);
  1249.     nokeyboard = (no_waiting == 1);
  1250.     norandom = (randomotion == 0);
  1251.     tracknr = findnr(&tracklist, trackfile);
  1252.     if (tracknr == ~0)
  1253.     {
  1254.         tracknr = 0;
  1255.     }
  1256.  
  1257.     /* initialize everything */
  1258.     init();
  1259.  
  1260.     /* event handling loop */
  1261.     idcmpmask = 1L << win_ptr->UserPort->mp_SigBit;
  1262.     while (done == FALSE)
  1263.     {
  1264.         signals = Wait(idcmpmask);
  1265.         if (signals & idcmpmask)
  1266.         {
  1267.             if (handlemsgs() != 0)
  1268.             {
  1269.                 done = TRUE;
  1270.             }
  1271.         }
  1272.     }
  1273.  
  1274.     /* get state */
  1275.     getstate();
  1276.  
  1277.     /* set RARS globals */
  1278.     lap_count = laps;
  1279.     race_count = races;
  1280.     practice = praclaps;
  1281.     surface = surfacetype;
  1282.     keep_order = (keeporder) ? (1) : (0);
  1283.     no_display = (nodisplay) ? (1) : (0);
  1284.     real_speed = (norealtime) ? (0) : (1);
  1285.     no_waiting = (nokeyboard) ? (1) : (0);
  1286.     rndmiz = (norandomseed) ? (0) : (1);
  1287.     randomotion = (norandom) ? (0) : (1);
  1288.     strcpy(trackfile, findname(&tracklist, tracknr));
  1289.     strcat(trackfile, ".trk");
  1290.  
  1291.     sprintf(envbuf_ptr, "TRACK=\"%s\" PRACTICELAPS=%d "
  1292.         "LAPS=%d RACES=%d SURFACETYPE=%d %s%s%s%s%s%s"
  1293.         "SCREENDEPTH=%d SCREENWIDTH=%d SCREENHEIGHT=%d SCREENMODEID=%d "
  1294.         "SCREENOVERSCANTYPE=%d %s",
  1295.         findname(&tracklist, tracknr),
  1296.         praclaps, laps, races, surfacetype,
  1297.         (keeporder) ? ("KEEPORDER ") : (""),
  1298.         (nodisplay) ? ("NODISPLAY ") : (""),
  1299.         (norealtime) ? ("NOREALTIME ") : (""),
  1300.         (nokeyboard) ? ("NOKEYBOARD ") : (""),
  1301.         (norandomseed) ? ("NORANDOMSEED ") : (""),
  1302.         (norandom) ? ("NORANDOM ") : (""),
  1303.         scrdepth, scrwidth, scrheight, scrid, scroscantype,
  1304.         (scrautoscroll) ? ("") : ("SCREENNOAUTOSCROLL"));
  1305.  
  1306.     /* list of drivers in the race */
  1307.     car_count = 0;
  1308.     node_ptr = drvsellist.lh_Head;
  1309.  
  1310.     strcat(envbuf_ptr, "DRIVERS");
  1311.  
  1312.     while (node_ptr->ln_Succ)
  1313.     {
  1314.         if ((i = finddriver(node_ptr->ln_Name)) == ~0UL)
  1315.         {
  1316.             break;
  1317.         }
  1318.         temp_drv = drivers[car_count];
  1319.         drivers[car_count] = drivers[i];
  1320.         drivers[i] = temp_drv;
  1321.  
  1322.         strcat(envbuf_ptr, " ");
  1323.         strcat(envbuf_ptr, node_ptr->ln_Name);
  1324.  
  1325.         /* next car */
  1326.         car_count++;
  1327.         node_ptr = node_ptr->ln_Succ;
  1328.     }
  1329.  
  1330.     if (saveenv)        
  1331.     {
  1332.         SetVar("RARSOPTS", envbuf_ptr, ENVBUFSIZE, GVF_GLOBAL_ONLY | GVF_SAVE_VAR);
  1333.     }
  1334.     else
  1335.     {
  1336.         SetVar("RARSOPTS", envbuf_ptr, ENVBUFSIZE, GVF_GLOBAL_ONLY);
  1337.     }
  1338.  
  1339.     /* save the window dimensions */
  1340.     sprintf(envbuf_ptr, "%d %d %d %d", win_ptr->LeftEdge, win_ptr->TopEdge, win_ptr->Width, win_ptr->Height);
  1341.     SetVar("RARSWINDOW", envbuf_ptr, ENVBUFSIZE, GVF_GLOBAL_ONLY | GVF_SAVE_VAR);
  1342.  
  1343.     /* cleanup everything */
  1344.     cleanup(NULL);
  1345.  
  1346.     /* if the user clicked on cancel or close, we quit */
  1347.     if (cancelrars)
  1348.     {
  1349.         exit(0);
  1350.     }
  1351. }
  1352.